import random

from django import http
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from meiduo_mall.apps.verifications import constans
from meiduo_mall.libs.captcha.captcha import captcha
from meiduo_mall.libs.yuntongxun.sms import CCP
from meiduo_mall.utlis.response_code import RET


class ImageCodeView(View):
    def get(self,request,image_code_id):
        #1,生成图片验证码
      	 # 1.利用captcha.py 的captcha.generate_captcha()方法返回3个数据:
   		 #①图片验证码的值
		#②图片验证码的值,
		#③带模糊功能的图片目的防止机械识别里边的值,只有人能识别
        name,text,image_data = captcha.generate_captcha()

        #2,保存图片验证码到redis中
        # 2.1 code是转码存放验证码的库,配置在dev里边
        # 2.2 get_redis_connection是系统的方法,可用于获取code库

        redis_conn = get_redis_connection("code")
        #redis_conn.setex方法保存redis数据->参数1: 保存到redis键,  参数2: 有效期,  参数3: 具体值
        redis_conn.setex("img_code_%s"%image_code_id,300,text)

        #3,返回图片验证码
        return http.HttpResponse(image_data,content_type="image/png")#定义image/png格式,不认会以文本解析

#发送短信验证吗
class SmsCodeView(View):
    def get(self,request,mobile):
        #1,获取参数,用户传进来的图形验证码跟验证码的值
        image_code = request.GET.get("image_code")#"image_code"是js路由里边？号后边定义的变量，并不是固定的image_code
        image_code_id = request.GET.get("image_code_id")#验证码的编号，redis通过他生成随机字符,js设定路由里边=号前边的内容

        # 2,校验参数
        # 2,1 为空校验
        if not all([image_code,image_code_id]):
            return http.JsonResponse({'code':RET.PARAMERR,'errmsg':'参数不完整'})

         # 2,2 获取redis中的图片验证码,校验为空
        redis_conn=get_redis_connection("code")
        pipeline=redis_conn.pipeline()#开启管道(事务)
        redis_image_code=redis_conn.get('img_code_%s'%image_code_id) #获取值不需要pipeline管道

        # 判断是否过期,过期redis_image_code会是一个空值
        if not redis_image_code:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "图片验证码过期"})

        # 删除redis验证码,因为已过期,删掉避免再次发给客户
        pipeline.delete('img_code_%s'%image_code_id)

        # 2,3 图片验证码正确性
        #2.4添加lower() 使验证码忽略大小写
        if image_code.lower() != redis_image_code.decode().lower():
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "图片验证码错误"})



         # 3,发送短信验证吗,并判断是否发送成功

        #3.1发送前先获取短信验证码标记是否存在(60s)

        send_flag=redis_conn.get('send_flag_%s'%mobile)#获取值不需要pipeline管道

        #判断是否存在,还存在代表没过60s,并返回短信频繁发送
        if send_flag:
            return http.JsonResponse({"code":RET.DATAERR,"errmsg":"短信发送频繁"},status=400)# status状态码



        #"%06d"%匹配规则是:匹配6个,不够的补0
        sms_code="%06d"%random.randint(0,999999)
        print("sms_code=%s"%sms_code)
        # ccp=CCP() #CCP()是yuntongxun文件夹里sms.py短信辅助类
        # # send_template_sms是yuntongxun文件夹里sms.py里发送短信的方法,(短信对象号码,[短信验证码,有效时间],1短信模板)
        # result=ccp.send_template_sms(mobile, [sms_code, constans.REDIS_IMAGE_COOD_EXPIRES], 1)
        # 判断是否发送成功,-1是云通讯规定的返回值
        # if result == -1:
        #     return http.JsonResponse({"code": RET.THIRDERR, "errmsg": "短信发送失败"})

        #使用celery发送短信,要启动celery耗时任务才能生效
        #耗时任务就是直接发送短信时，需要等待一段时间，这段时间内不能往下执行命令
        #而使用了耗时任务中的delay方法，则不需要等待就可以机继续往下执行
        #不想用耗时任务可以直接用发送短信的那段代码复制进来用
        from celery_tasks.sms.tasks import send_sms_code
        send_sms_code.delay(mobile,sms_code,constans.REDIS_SMS_COOD_EXPIRES/60)
         # 保存短信验证到redis
         # 保存对象有:手机号,保存5*60s,短信验证码 .以键值对方式存放,可以通过手机号获取验证码
        pipeline.setex("sms_code_%s"%mobile,constans.REDIS_SMS_COOD_EXPIRES,sms_code)

        # 保存并标记短信验证码有效时间为60s,mobile是键,True是代表存在验证码(给验证码做标记)
        pipeline.setex('send_flag_%s'%mobile,60,1)#60s后这个键值对就不存在,1代表True,但是这里不能写True,redis 3.2.1 版本不支持bool类型,所以用1

        # 提交管道(事务)
        pipeline.execute()
        # 4,返回响应
        return http.JsonResponse({"code": RET.OK, "errmsg": "ok"})
